package cn.stylefeng.guns.modular.auth.service.impl;

import cn.stylefeng.guns.modular.auth.domain.composite.PriorityNode;
import cn.stylefeng.guns.modular.auth.domain.visitor.PriorityNodeRelateCheckVisitor;
import cn.stylefeng.guns.modular.auth.domain.visitor.PriorityNodeRemoveVisitor;
import cn.stylefeng.guns.modular.auth.service.AuthAccountPriorityRelationshipService;
import cn.stylefeng.guns.modular.auth.service.AuthRolePriorityRelationshipService;
import cn.stylefeng.guns.modular.auth.utils.converter.AuthPriorityEntity2NodeConverter;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.stylefeng.guns.modular.auth.domain.dto.AuthPriorityDTO;
import cn.stylefeng.guns.modular.auth.entity.AuthPriorityEntity;
import cn.stylefeng.guns.modular.auth.mapper.AuthPriorityMapper;
import cn.stylefeng.guns.modular.auth.service.AuthPriorityService;
import cn.stylefeng.guns.modular.auth.utils.converter.AuthPriorityEntity2DTOConverter;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author allen
 * @version 1.0
 * @date 2021/4/12 10:07
 */

@Service
public class AuthPriorityServiceImpl extends ServiceImpl<AuthPriorityMapper, AuthPriorityEntity> implements AuthPriorityService {


    @Resource
    private AuthPriorityEntity2DTOConverter authPriorityEntity2DtoConverter;
    @Resource
    private AuthPriorityEntity2NodeConverter authPriorityEntity2NodeConverter;

    @Resource
    AuthAccountPriorityRelationshipService authAccountPriorityRelationshipService;
    @Resource
    AuthRolePriorityRelationshipService authRolePriorityRelationshipService;
    @Resource
    private AuthPriorityMapper authPriorityMapper;

    @Override
    public int updateBatch(List<AuthPriorityEntity> list) {
        return baseMapper.updateBatch(list);
    }

    @Override
    public int updateBatchSelective(List<AuthPriorityEntity> list) {
        return baseMapper.updateBatchSelective(list);
    }

    @Override
    public int batchInsert(List<AuthPriorityEntity> list) {
        return baseMapper.batchInsert(list);
    }

    @Override
    public int insertOrUpdate(AuthPriorityEntity record) {
        return baseMapper.insertOrUpdate(record);
    }

    @Override
    public int insertOrUpdateSelective(AuthPriorityEntity record) {
        return baseMapper.insertOrUpdateSelective(record);
    }

    @Override
    public List<AuthPriorityDTO> listRootPriorities() {


//        this.lambdaQuery().list().stream().


        List<AuthPriorityEntity> list = this.lambdaQuery()
                .isNull(AuthPriorityEntity::getParentId)
                .list();


        List<AuthPriorityDTO> authPriorityDTOS = authPriorityEntity2DtoConverter.sourceToTarget(list);


        return authPriorityDTOS;
    }

    /**
     * 根据父权限id查询权限列表
     *
     * @param parentId 父权限id
     * @return dto列表
     */
    @Override
    public List<AuthPriorityDTO> getPrioritiesByParentId(Long parentId) {

        List<AuthPriorityEntity> list = this.lambdaQuery().eq(AuthPriorityEntity::getParentId, parentId).list();
        List<AuthPriorityDTO> authPriorityDTOS = authPriorityEntity2DtoConverter.sourceToTarget(list);


        return authPriorityDTOS;

    }

    @Override
    public AuthPriorityDTO getPrioritiesById(Long id) {
        AuthPriorityEntity one = this.lambdaQuery().select(AuthPriorityEntity::getId).one();
        return authPriorityEntity2DtoConverter.sourceToTarget(one);
    }

    /**
     * 第一，你必须先删除最底层的子权限，然后一级一级往上删除，删除到当前的权限
     * <p>
     * 第二，你除了删除权限之外，你还得care一下角色、账号跟权限之间的关联关系，
     * 我们要做一个check，也就是说，如果这个权限还跟有一些角色和账号跟之进行关联，就不能直接删除
     * 根据id删除权限
     *
     * @param id 权限id
     * @return 处理结果 true代表删除成功   false代表删除失败
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteById(Long id) {

//        relateCheckVisitor
//        remove
        AuthPriorityEntity byId = this.getById(id);
        PriorityNode priorityNode = authPriorityEntity2NodeConverter.sourceToTarget(byId);


        PriorityNodeRelateCheckVisitor visitor1 = new PriorityNodeRelateCheckVisitor(this,
                authAccountPriorityRelationshipService,
                authRolePriorityRelationshipService);
        visitor1.visit(priorityNode);
        Boolean result = visitor1.getRelateCheckResult();
        if (result) {
            return false;
        }

        PriorityNodeRemoveVisitor visitor2 = new PriorityNodeRemoveVisitor(this);
        visitor2.visit(priorityNode);


        return true;
    }
}
